package com.space.components.domain.core.diff;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:414563035@qq.com">Bedroom</a>
 * @date 2021/5/24 6:24 下午
 */
public class EntityDiff<T> {
    private final Class<T> clazz;
    private final List<EntityNode> entityNodes;
    private final Map<String, Field> fields;

    public EntityDiff(Class<T> clazz, Map<String, Field> fields) {
        this.entityNodes = new ArrayList<>();
        this.clazz = clazz;
        this.fields = fields;
    }

    public boolean isSelfModified() {
        return !entityNodes.isEmpty();
    }

    public void add(EntityNode entityNode) {
        this.entityNodes.add(entityNode);
    }

    public <R> R get(String name) {
        for (EntityNode entityNode : entityNodes) {
            if (entityNode.getName().equals(name)) {
                return (R) entityNode.getValue();
            }
        }
        throw new RuntimeException("找不到类型: " + clazz);
    }

    public <R> EntityDiff<R> getEntity(String name) {
        for (EntityNode entityNode : entityNodes) {
            final Object value = entityNode.getValue();
            if (entityNode.getName().equals(name) && value instanceof ArrayDiff) {
                return (EntityDiff<R>) value;
            }
        }
        throw new RuntimeException("找不到类型: " + clazz);
    }

    public <A> ArrayDiff<A> getArrayDiff(String name) {
        return getArrayDiff(name, null);
    }

    public <A> ArrayDiff<A> getArrayDiff(String name, Class<A> type) {
        for (EntityNode entityNode : entityNodes) {
            final Object value = entityNode.getValue();
            if (entityNode.getName().equals(name) && value instanceof ArrayDiff) {
                return (ArrayDiff<A>) value;
            }
        }
        throw new RuntimeException("找不到: " + name);
    }

    public <R> EntityDiff<R> get(Class<R> clazz) {
        for (EntityNode entityNode : entityNodes) {
            System.out.println(entityNode.getType());
            if (entityNode.getType() == clazz) {
                return (EntityDiff<R>) entityNode.getValue();
            }
        }
        throw new RuntimeException("找不到类型: " + clazz);
    }

    public T toSelfDiffEntity() {
        T entity = null;
        try {
            entity = clazz.getDeclaredConstructor().newInstance();
            for (EntityNode entityNode : entityNodes) {
                final Object value = entityNode.getValue();
                final Field field = this.fields.get(entityNode.getName());
                // 不反射Entity和List
                if (!(value instanceof EntityDiff) && !(value instanceof ArrayDiff)) {
                    field.set(entity, entityNode.getValue());
                }
//                if (value instanceof EntityDiff) {
////                    field.set(entity, ((EntityDiff<?>) entityNode.getValue()).toDiffEntity());
//                } else if (value instanceof ArrayDiff) {
//                    // 不反射
////                    ((ArrayDiff<?>) value).forEach(System.out::println);
//                } else {
//                    field.set(entity, entityNode.getValue());
//                }
            }
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }

        return entity;
    }

    @Override
    public String toString() {
        return "EntityDiff{" +
                "clazz=" + clazz +
                ", entityNodes=" + entityNodes +
                ", fields=" + fields +
                '}';
    }
}
